<template>
  <div class="handler-task">
    <van-nav-bar class="header" style="flex-grow: 0;"
      left-arrow
      @click-left="onBack()"
    >
      <template #title>
        <p style="font-size: 16px;color: #333333;font-weight: 400;">任务详情</p>
      </template>
      <template #left>
        <van-icon name="arrow-left" size="18" color="#3B3938" />
      </template>
    </van-nav-bar>
    <!-- 任务信息 -->
    <div class="task-info-box">
      <div class="content">
        <span class="title">{{ flowEntryName }}</span>
        <span v-if="taskName" class="sub-title">当前任务：{{ taskName }}</span>
        <van-row v-if="processInstanceId != null" class="menu-box" type="flex" justify="space-between" align="center">
          <div class="user-box">
            <van-avatar width="24px" height="24px"
              font-size="12px" round
              style="margin-right: 5px;"
              :src="headImageUrl"
              :text="processInstanceInitiator"
            />
            <span class="userName">{{ processInstanceInitiator }}</span>
          </div>
        </van-row>
      </div>
      <van-image v-if="statusImage" class="process-status" :src="statusImage" />
    </div>
    <!-- 任务详情 -->
    <van-tabs class="task-detail" v-if="processInstanceId != null && !isDraft" label="approveInfo"
      :class="{'no-operation': mainOperation.length <= 0}" v-model="active" color="#ff7700" title-active-color="#ff7700"
      title-inactive-color="#666666" line-width="20"
    >
      <van-tab title="表单详情" name="form" title-style="font-size:16px;">
        <div class="form-box">
          <online-form v-if="formId != null && formId !== ''" ref="workflowForm" :formId="formId" :flowInfo="getFlowInfo" :readOnly="isReadOnly" />
          <router-view v-else ref="routerFlowForm" style="width: 100%;"
            :isRuntimeTask="isRuntime"
            :isDraft="isDraft"
            :readOnly="isReadOnly"
            :processInstanceId="processInstanceId"
            :taskId="taskId"
            :taskVariableList="variableList"
          />
          <CopyForSelect v-if="processInstanceId == null || isRuntime || isRuntime === 'true' || isDraft || isDraft === 'true'"
            style="margin: 16px 16px 0px 16px;" v-model="copyItemList" />
        </div>
      </van-tab>
      <van-tab title="审批记录" name="approveInfo" title-style="font-size:16px;">
        <div class="">
          <taskFlow :processInstanceId="processInstanceId"></taskFlow>
        </div>
      </van-tab>
    </van-tabs>
    <div v-else class="task-detail">
      <div class="start-form-box">
        <online-form v-if="formId != null && formId !== ''" ref="workflowForm" :formId="formId" :flowInfo="getFlowInfo" :readOnly="isReadOnly" />
        <router-view v-else ref="routerFlowForm" style="width: 100%;"
          :isRuntimeTask="isRuntime"
          :isDraft="isDraft"
          :readOnly="isReadOnly"
          :processInstanceId="processInstanceId"
          :taskId="taskId"
          :taskVariableList="variableList"
        />
        <CopyForSelect style="margin: 16px 16px 0px 16px;" v-model="copyItemList" />
      </div>
    </div>
    <!-- 按钮栏 -->
    <van-row v-if="active === 'form' && (mainOperation.length > 0)" class="task-operation" type="flex" align="center">
      <van-popover v-if="moreActions.length > 0"
        v-model="showActions"
        trigger="click"
        placement="top-start"
        :actions="moreActions"
        @select="(action) => handlerOperation(action.operation)"
      >
        <template #reference>
          <van-icon class="more-operation" name="ellipsis" size="20px" color="#333333" />
        </template>
      </van-popover>
      
      <van-button class="main-operation" v-for="(operation, index) in mainOperation" :key="index"
        :type="getButtonType(operation.type)"
        @click="handlerOperation(operation)"
      >
        {{ operation.label }}
      </van-button>
    </van-row>
    <!-- 提交数据 -->
    <van-popup
      v-if="showCommitDlg"
      v-model="showCommitDlg"
      position="right"
      get-container="body"
      :overlay="false"
      style="height: 100vh; width: 100vw; background: #F6F6F6;"
    >
      <TaskCommit v-if="showCommitDlg" :title="commitInfo.title"
        :operation="commitInfo.operation"
        :processInstanceId="commitInfo.processInstanceId"
        :taskId="commitInfo.taskId"
        :processDefinitionId="processDefinitionId"
        :finishedInfo="commitInfo.finishedInfo"
        @close="onTaskCommitCallback"
      />
    </van-popup>
  </div>
</template>

<script>
import { Notify } from 'vant';
import flowMixins from '../mixins/flowMixins';
import CopyForSelect from '../components/copyForSelect/index.vue';
import TaskCommit from '../components/taskCommit.vue';
import taskFlow from '../components/taskCommentList.vue';
import { FlowOperationController } from '@/api/flowController.js';

export default {
  name: 'handlerFlowTask',
  props: {
    isRuntime: {
      type: [Boolean, String]
    },
    isDraft: {
      type: [Boolean, String]
    },
    isPreview: {
      type: [Boolean, String]
    },
    // 流程标识
    processDefinitionKey: {
      type: String
    },
    // 在线表单formId
    formId: {
      type: String
    },
    // 路由名称
    routerName: {
      type: String
    },
    // 只读页面
    readOnly: {
      type: [String, Boolean]
    },
    // 消息id，用于抄送消息回显
    messageId: {
      type: String
    },
    // 流程实例id
    processInstanceId: {
      type: String
    },
    // 流程定义id
    processDefinitionId: {
      type: String
    },
    // 当前任务节点id
    taskId: {
      type: String
    },
    // 流程名称
    flowEntryName: {
      type: String
    },
    // 发起人
    processInstanceInitiator: {
      type: String
    },
    // 发起人头像
    headImageUrl: {
      type: String
    },
    // 当前任务节点名称
    taskName: {
      type: String
    },
    // 当前任务节点操作列表
    operationList: {
      type: Array
    },
    // 当前任务节点变量列表
    variableList: {
      type: Array
    },
    // 流程状态
    flowStatus: {
      type: [Number, String]
    }
  },
  components: {
    CopyForSelect,
    TaskCommit,
    taskFlow
  },
  mixins: [flowMixins],
  data () {
    return {
      active: 'form',
      showCommitDlg: false,
      showActions: false,
      dlgTitle: '提交',
      statusImg: require('@/assets/icon/approval-icon.png'),
      passImg: require('@/assets/icon/pass-icon.png'),
      refuseImg: require('@/assets/icon/refuse-icon.png'),
      draftImg: require('@/assets/icon/draft-icon.png'),
      cancelImg: require('@/assets/icon/cancel-icon.png'),
      stoppedImg: require('@/assets/icon/stopped-icon.png'),
      flowInfo: {
        taskName: this.taskName,
        flowEntryName: this.flowEntryName,
        processInstanceInitiator: this.processInstanceInitiator,
        headerUrl: undefined
      },
      copyItemList: [],
      commitInfo: {
        operation: undefined,
        processInstanceId: undefined,
        taskId: undefined,
        formData: undefined,
        finishedInfo: undefined
      },
      previousRouterName: null
    }
  },
  methods: {
    onBack () {
      console.log('onBack', this.$router, this.$route.fullPath);
      this.$router.go(-1);
      setTimeout(() => {
        console.log('onBack', this.$router, this.$route.fullPath);
      }, 1000);
    },
    /**
     * 获得路由组件下的函数
     * @param {string} functionName 函数名称
     * @returns {function}
     */
    getRouterCompomentFunction (functionName) {
      return (this.$refs.routerFlowForm && typeof this.$refs.routerFlowForm[functionName] === 'function') ? this.$refs.routerFlowForm[functionName] : undefined;
    },
    startImpl (operation, formData, copyItemList) {
      if (this.isOnlineForm) {
        FlowOperationController.startAndTakeUserTask(this, {
          processDefinitionKey: this.processDefinitionKey,
          masterData: formData.masterData || {},
          slaveData: formData.slaveData,
          taskVariableData: {
            ...formData.taskVariableData,
            latestApprovalStatus: operation.latestApprovalStatus
          },
          flowTaskCommentDto: {
            approvalType: operation.type
          },
          copyData: (copyItemList || []).reduce((retObj, item) => {
            retObj[item.type] = item.id;
            return retObj;
          }, {})
        }).then(res => {
          Notify({ type: 'success', message: '启动成功！' });
          this.handlerClose();
        }).catch(e => {});
      } else {
        let startImpl = this.getRouterCompomentFunction('startImpl');
        if (startImpl) {
          startImpl(operation, formData, copyItemList).then(res => {
            this.handlerClose();
          }).catch(e => {});
        } else {
          this.$message.error('当前流程并未实现启动功能，请联系管理员！');
        }
      }
    },
    submitImpl (operation, formData, copyItemList, taskCommitData) {
      return new Promise((resolve, reject) => {
        if (this.isOnlineForm) {
          // 在线表单数据提交
          let params = {
            taskId: this.taskId,
            processInstanceId: this.processInstanceId,
            masterData: formData.masterData,
            slaveData: formData.slaveData,
            flowTaskCommentDto: {
              taskComment: (taskCommitData || {}).message,
              approvalType: operation.type,
              delegateAssignee: operation.type === this.SysFlowTaskOperationType.TRANSFER ? (taskCommitData || {}).assignee : undefined
            },
            taskVariableData: {
              ...formData.taskVariableData,
              latestApprovalStatus: operation.latestApprovalStatus
            },
            copyData: (copyItemList || []).reduce((retObj, item) => {
              retObj[item.type] = item.id;
              return retObj;
            }, {})
          }

          FlowOperationController.submitUserTask(this, params).then(res => {
            this.reloadMessage(this);
            Notify({ type: 'success', message: '提交成功！' });
            resolve();
          }).catch(e => {
            reject(e);
          });
        } else {
          let submitImpl = this.getRouterCompomentFunction('submitImpl');
          if (submitImpl) {
            submitImpl(operation, formData, copyItemList, taskCommitData).then(res => {
              resolve();
            }).catch(e => {
              reject(e);
            });
          } else {
            this.$message.error('当前流程并未实现提交功能，请联系管理员！');
            reject();
          }
        }
      });
    },
    getButtonType (type) {
      switch (type) {
        case this.SysFlowTaskOperationType.AGREE:
        case this.SysFlowTaskOperationType.TRANSFER:
        case this.SysFlowTaskOperationType.CO_SIGN:
        case this.SysFlowTaskOperationType.SIGN_REDUCTION:
        case this.SysFlowTaskOperationType.BFORE_CONSIGN:
        case this.SysFlowTaskOperationType.AFTER_CONSIGN:
        case this.SysFlowTaskOperationType.MULTI_AGREE:
        case this.SysFlowTaskOperationType.MULTI_SIGN:
        case this.SysFlowTaskOperationType.SET_ASSIGNEE:
          return 'primary';
        case this.SysFlowTaskOperationType.SAVE:
          return 'success';
        case this.SysFlowTaskOperationType.REFUSE:
        case this.SysFlowTaskOperationType.PARALLEL_REFUSE:
        case this.SysFlowTaskOperationType.MULTI_REFUSE:
          return 'default';
        case this.SysFlowTaskOperationType.REJECT:
        case this.SysFlowTaskOperationType.REJECT_TO_START:
        case this.SysFlowTaskOperationType.REJECT_TO_TASK:
        case this.SysFlowTaskOperationType.REVOKE:
          return 'danger';
        default: return 'default';
      }
    },
    handlerOperation (operation) {
      if (this.processInstanceId == null && this.taskId == null) {
        this.handlerStart(operation, this.copyItemList);
      } else {
        this.handlerSubmit(operation, this.copyItemList);
      }
    },
    async handlerSubmit (operation, copyItemList) {
      let formData = await this.getMasterData(operation.type);
      this.preHandlerOperation(operation, false, copyItemList, formData).then(taskCommitData => {
        if (formData) formData = this.buildFormData(operation, formData, taskCommitData);
        this.onTaskCommitCallback(true, taskCommitData);
      }).catch(e => {
        console.log(e);
      });
    },
    async handlerStart (operation, copyItemList) {
      let formData = await this.getMasterData(operation.type);
      this.preHandlerOperation(operation, true, copyItemList, formData).then(taskCommitData => {
        if (formData) {
          formData = this.buildFormData(operation, formData, taskCommitData);
          this.startImpl(operation, formData, copyItemList).then(() => {
            this.handlerClose();
          }).catch(e => {});
        }
      }).catch(e => {});
    },
    handlerClose () {
      this.$router.back();
    },
    buildFormData (operation, formData, taskCommitData) {
      let assignee = ((taskCommitData || {}).assignee || '').split(',');
      if (operation.type === this.SysFlowTaskOperationType.MULTI_SIGN) {
        // 会签操作设置多实例处理人集合
        if (formData.taskVariableData == null) formData.taskVariableData = {};
        formData.taskVariableData.assigneeList = assignee;
      } else if (operation.type === this.SysFlowTaskOperationType.SET_ASSIGNEE) {
        // 设置下一个任务节点处理人
        if (formData.taskVariableData == null) formData.taskVariableData = {};
        formData.taskVariableData.appointedAssignee = Array.isArray(assignee) ? assignee.join(',') : undefined;
      }
      return formData;
    },
    async getMasterData (operationType) {
      // 不需要获取表单数据的操作
      let tempList = [
        this.SysFlowTaskOperationType.CO_SIGN,
        this.SysFlowTaskOperationType.SIGN_REDUCTION,
        this.SysFlowTaskOperationType.BFORE_CONSIGN,
        this.SysFlowTaskOperationType.AFTER_CONSIGN,
        this.SysFlowTaskOperationType.FREE_JUMP,
        this.SysFlowTaskOperationType.REJECT,
        this.SysFlowTaskOperationType.REJECT_TO_TASK,
        this.SysFlowTaskOperationType.REJECT_TO_START,
        this.SysFlowTaskOperationType.REVOKE
      ];
      if (tempList.indexOf(operationType) !== -1) return Promise.resolve();
      if (!this.isOnlineForm) {
        // 获得静态表单页面的getMasterData函数
        let funGetMasterData = this.getRouterCompomentFunction('getMasterData');
        if (funGetMasterData != null) {
          return funGetMasterData(this.variableList);
        } else {
          throw new Error('当前流程并未实现获取表单数据功能，请联系管理员！');
        }
      } else {
        if (this.$refs.workflowForm && typeof this.$refs.workflowForm.getFormData === 'function') {
          let formData = await this.$refs.workflowForm.getFormData(false, this.variableList);
          return formData;
        } else {
          throw new Error('当前流程并未实现获取表单数据功能，请联系管理员！');
        }
      }
    },
    onTaskCommitCallback (success, taskCommitData) {
      let operation = this.commitInfo.operation;
      let formData = this.commitInfo.formData;
      let copyItemList = this.copyItemList;
      if (success) {
        // 加签、减签操作
        if (operation.type === this.SysFlowTaskOperationType.CO_SIGN ||
          operation.type === this.SysFlowTaskOperationType.SIGN_REDUCTION ||
          operation.type === this.SysFlowTaskOperationType.BFORE_CONSIGN |
          operation.type === this.SysFlowTaskOperationType.AFTER_CONSIGN
        ) {
          // 串行会签前后加签参数
          let after;
          if (
            operation.type === this.SysFlowTaskOperationType.BFORE_CONSIGN ||
            operation.type === this.SysFlowTaskOperationType.AFTER_CONSIGN
          ) {
            after = operation.type === this.SysFlowTaskOperationType.BFORE_CONSIGN;
          }
          this.submitConsign(
            (taskCommitData || {}).assignee,
            operation.type === this.SysFlowTaskOperationType.CO_SIGN,
            after
          )
            .then(res => {
              this.handlerClose();
            })
            .catch(e => {});
          return;
        }
        // 自由跳
        if (operation.type === this.SysFlowTaskOperationType.FREE_JUMP) {
          FlowOperationController.freeJump(this, {
            processInstanceId: this.processInstanceId,
            sourceTaskId: this.taskId,
            targetTaskKey: (taskCommitData || {}).targetTaskKey,
            delegateAssignee: (taskCommitData || {}).assignee,
            taskComment: (taskCommitData || {}).message,
            taskVariableData: {
              latestApprovalStatus: operation.latestApprovalStatus
            }
          }).then(res => {
            this.handlerClose();
          }).catch(e => {});
          return;
        }
        // 驳回操作
        if (operation.type === this.SysFlowTaskOperationType.REJECT || operation.type === this.SysFlowTaskOperationType.REJECT_TO_TASK) {
          FlowOperationController.rejectRuntimeTask(this, {
            processInstanceId: this.processInstanceId,
            taskId: this.taskId,
            targetTaskKey: (taskCommitData || {}).targetTaskKey,
            taskComment: (taskCommitData || {}).message,
            taskVariableData: {
              latestApprovalStatus: operation.latestApprovalStatus
            }
          }).then(res => {
            this.handlerClose();
          }).catch(e => {});
          return;
        }
        // 驳回到起点
        if (operation.type === this.SysFlowTaskOperationType.REJECT_TO_START) {
          FlowOperationController.rejectToStartUserTask(this, {
            processInstanceId: this.processInstanceId,
            taskId: this.taskId,
            taskComment: (taskCommitData || {}).message,
            taskVariableData: {
              latestApprovalStatus: operation.latestApprovalStatus
            }
          }).then(res => {
            this.handlerClose();
          }).catch(e => {});
          return;
        }
        // 撤销操作
        if (operation.type === this.SysFlowTaskOperationType.REVOKE) {
          this.$dialog.confirm({
            title: '提示',
            message: '是否撤销此任务？'
          }).then(res => {
            FlowOperationController.revokeHistoricTask(this, {
              processInstanceId: this.processInstanceId,
              taskId: this.taskId,
              taskComment: '任务处理人撤销任务',
              taskVariableData: {
                latestApprovalStatus: operation.latestApprovalStatus
              }
            }).then(res => {
              this.handlerClose();
            }).catch(e => {});
          }).catch(e => {});
          return;
        }
        this.submitImpl(operation, formData, copyItemList, taskCommitData).then(() => {
          this.handlerClose();
        }).catch(e => {});
      }
      this.showCommitDlg = false;
    }
  },
  computed: {
    isOnlineForm () {
      return this.formId != null;
    },
    statusImage () {
      switch (Number.parseInt(this.flowStatus)) {
        case this.SysFlowWorkOrderStatus.APPROVING:
        case this.SysFlowWorkOrderStatus.SUBMITED:
          // 审批中
          return this.statusImg;
        case this.SysFlowWorkOrderStatus.STOPPED:
          // 终止
          return this.stoppedImg;
        case this.SysFlowWorkOrderStatus.REFUSED:
          // 拒绝
          return this.refuseImg;
        case this.SysFlowWorkOrderStatus.FINISHED:
          // 通过
          return this.passImg;
        case this.SysFlowWorkOrderStatus.CANCEL:
          // 撤销
          return this.cancelImg;
        case this.SysFlowWorkOrderStatus.DRAFT:
          // 草稿
          return this.draftImg;
        default:
          return null;
      }
    },
    flowOperation () {
      if (Array.isArray(this.operationList)) {
        return this.operationList.map(item => {
          if (item.type === this.SysFlowTaskOperationType.MULTI_SIGN && item.multiSignAssignee != null) {
            let multiSignAssignee = {
              ...item.multiSignAssignee
            }
            multiSignAssignee.assigneeList = item.multiSignAssignee.assigneeList ? multiSignAssignee.assigneeList.split(',') : undefined;
            return {
              ...item,
              multiSignAssignee
            }
          } else {
            return {
              ...item
            }
          }
        });
      } else {
        return [];
      }
    },
    mainOperation () {
      return this.flowOperation.slice(0, 2);
    },
    moreOperation () {
      return this.flowOperation.slice(2);
    },
    moreActions () {
      return this.moreOperation.map(operation => {
        return {
          text: operation.label,
          operation: operation
        }
      });
    },
    getFlowInfo () {
      return {
        processInstanceId: this.processInstanceId,
        taskId: this.taskId,
        processDefinitionKey: this.processDefinitionKey,
        processInstanceInitiator: this.processInstanceInitiator,
        messageId: this.messageId,
        isRuntime: this.isRuntime,
        isDraft: this.isDraft
      }
    },
    isReadOnly () {
      return typeof this.readOnly === 'string' ? this.readOnly === 'true' : this.readOnly;
    }
  },
  mounted () {
    // 判断操作列表和变量列表是否为数组
    if ((this.operationList && !Array.isArray(this.operationList)) ||
      (this.variableList && !Array.isArray(this.variableList))) {
      this.$router.back();
    }
    // 判断操作列表和变量列表中的数据是否为字符串。如果是刷新页面那么传入的数组中的数据会变成字符串，这时候需要返回上一页
    if ((this.operationList && this.operationList[0] != null && typeof this.operationList[0] === 'string') ||
      (this.variableList && this.variableList[0] != null && typeof this.variableList[0] === 'string')) {
      this.$router.back();
    }
  }
}
</script>

<style scoped>
  .handler-task {
    display: flex;
    flex-direction: column;
    height: 100vh;
  }
  .task-info-box {
    display: flex;
    background: white;
    padding: 16px;
    flex-grow: 0;
    flex-shrink: 0;
  }
  .task-info-box .content {
    flex-grow: 1;
    flex-shrink: 1;
  }
  .task-info-box .process-status {
    flex-grow: 0;
    flex-shrink: 0;
    width: 67px;
    height: 53px;
    margin-left: 15px;
    margin-top: 15px;
  }
  .title {
    display: block;
    font-weight: bold;
    color: #333333;
    line-height: 20px;
    height: 20px;
    font-size: 16px;
  }
  .sub-title {
    display: block;
    color: #666666;
    line-height: 20px;
    height: 20px;
    font-size: 14px;
    font-weight: 400;
    margin-top: 10px;
  }
  .userName{
    font-size: 12px;
    color: #666666;
    font-weight: 400;
    line-height: 24px;
  }
  .task-info-box .menu-box {
    margin-top: 10px;
  }
  .task-info-box .menu-box .user-box {
    height: 24px;
    display: flex;
    align-items: center;
  }
  .task-info-box .menu-box .user-box .text {
    color: #666666;
    font-size: 12px;
  }
  .task-operation {
    height: 64px;
    background: white;
    border-top: 1px solid #E8E8E8;
    padding: 0px 16px;
    flex-grow: 0;
    flex-shrink: 0;
  }
  .task-operation .more-operation {
    margin-right: 16px;
    flex-grow: 0;
    flex-shrink: 0;
    width: 24px;
  }
  .task-operation .main-operation {
    flex-grow: 1;
    flex-shrink: 1;
    width: 24px;
  }
  .main-operation + .main-operation {
    margin-left: 8px;
  }
  .task-detail {
    flex-grow: 1;
    flex-shrink: 1;
    border-top: 1px solid #E8E8E8;
    overflow: hidden;
  }
  .task-detail .form-box {
    height: calc(100vh - 306px);
    margin: 16px 0px;
    overflow: auto;
  }
  .task-detail.no-operation .form-box {
    height: calc(100vh - 242px);
  }
  .task-detail .start-form-box {
    height: calc(100% - 32px);
    margin: 16px 0px;
    overflow: auto;
  }

  .copy-for {
    border-radius: 8px;
    background: white;
    margin: 0px 16px;
    padding: 16px;
  }
</style>
